package com.dns.reset.core;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.telnet.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;

public class TelnetUtil  implements Runnable, TelnetNotificationHandler {
    Logger logger = LoggerFactory.getLogger(TelnetUtil.class);
    private TelnetClient tc = null;
    private String remoteip;
    private int remoteport;
    private String remoteName;
    private String username;
    private String password;
    InputStream instr;
    private PrintStream out;
    private static final String ORIG_CODEC = "ISO8859-1";
    private static final String TRANSLATE_CODEC = "GBK";

    private StringBuffer responseStr = new StringBuffer();

    /**

     * 最终构造方法

     *

     * @param ip

     * @param port

     * @param

     */
    public TelnetUtil(String ip, int port,String username, String password,String deviceName) {
        remoteip = ip;
        remoteport = port;
        this.remoteName = deviceName;
        this.username = username;
        this.password=password;
        initClient();

    }

    public boolean isConnected(){
        return tc.isConnected();
    }

	/*public TelnetUtil(String ip, int port, String username, String password,String deviceName)

			throws Exception {

		this(ip, port,username,password,deviceName);

		this.connect(2000);

		//this.login(username, password);

		//this.remoteName = deviceName;

		//this.username = username;

		//this.password=password;



	}*/

    private void initClient() {

        tc = new TelnetClient();

        TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler(
                "VT220", false, false, true, false);
        EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true,
                false);
        SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true,
                true, true);

        try {
            tc.addOptionHandler(ttopt);
            tc.addOptionHandler(echoopt);
            tc.addOptionHandler(gaopt);
            this.connect(2000);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

    }

    private String connect(long waitTime) throws Exception {
        try {
            logger.info("telnet 登陆服务器{}....",remoteip);
            tc.connect(remoteip, remoteport);

            //Thread reader = new Thread(this);

            tc.registerNotifHandler(this);
            instr = tc.getInputStream();
            out = new PrintStream(tc.getOutputStream());
            readUntil("Username:");
            write(this.username);
            write("\n");
            readUntil("Password:");
            write(this.password);
            write("\n");
            //reader.start();

            logger.info("telnet连接成功.....");
            return getResponse(waitTime);
        } catch (Exception e) {
            throw new Exception("telnet 连接失败", e);
        }
    }

    public void login(String username, String password) throws Exception {
        this.connect(2000);
        this.sendCommand(username);
        this.sendCommand(password);
        System.out.println(getResponse(100));
    }
    public void disConnect() throws IOException {
        if (tc != null && tc.isConnected())
            tc.disconnect();
    }

    /**

     * 发送命令,返回结果请调用 getResponse(long waitTime)

     *

     * @param command

     * @throws Exception

     */
    public void sendCommand(String command) throws Exception {

        try {
            responseStr.delete(0, responseStr.capacity());
            OutputStream outstr = tc.getOutputStream();
            if(StringUtils.isBlank(command)){
                command = "\n";
            }
            outstr.write(command.getBytes());
            outstr.write(13);
            outstr.write(10);
            outstr.flush();
        } catch (Exception e) {
            throw new Exception("telnet 发送命令[" + command + "]失败", e);
        }

    }

    /**

     * 发送命令

     *

     * @param command

     *            命令

     * @param waitTime

     *            获取返回结果时等待时间，在等待的时间内若返回的结果不是想要的结果，可以调用 getResponse(long

     *            waitTime)继续获取

     * @return 执行结果

     * @throws Exception

     */
    public String sendCommand(String command, int waitTime) throws Exception {

        try {
            responseStr.delete(0, responseStr.capacity());
            OutputStream outstr = tc.getOutputStream();

            outstr.write(command.getBytes());
            outstr.write(13);
            outstr.write(10);
            outstr.flush();
        } catch (Exception e) {
            throw new Exception("telnet 发送命令[" + command + "]失败", e);
        }

        return getResponse(command, waitTime);

    }

    public void receivedNegotiation(int negotiation_code, int option_code) {
        String command = null;
        if (negotiation_code == TelnetNotificationHandler.RECEIVED_DO) {
            command = "DO";
        } else if (negotiation_code == TelnetNotificationHandler.RECEIVED_DONT) {
            command = "DONT";
        } else if (negotiation_code == TelnetNotificationHandler.RECEIVED_WILL) {
            command = "WILL";
        } else if (negotiation_code == TelnetNotificationHandler.RECEIVED_WONT) {
            command = "WONT";
        }
        logger.debug("Received " + command + " for option code " + option_code);
    }

    /***

     * Reader thread. Reads lines from the TelnetClient and echoes them on the

     * screen.

     ***/
    // @Override

    public void run() {
        //InputStream instr = tc.getInputStream();


        try {
            byte[] buff = new byte[1024];
            int ret_read = 0;

            do {
                ret_read = instr.read(buff);
                if (ret_read > 0) {
                    responseStr.append(new String(buff, 0, ret_read).replaceAll("\t", ""));
                }
            } while (ret_read >= 0);
        } catch (Exception e) {

            logger.error("Exception while reading socket:" + e.getMessage());
        }
    }

    /**

     * 获取命令返回去

     *

     * @param waitTime

     *            等待时间

     * @return

     */
    private String getResponse(long waitTime) {
		/*try {

			Thread.sleep(waitTime);

			} catch (InterruptedException e) {

			e.printStackTrace();

		}*/
        return readUntil(null,waitTime);
    }

    /**

     * 获取命令返回去

     *

     * @param cmd

     *            执行的命令

     * @param waitTime

     *            等待时间

     * @return

     */
    public String getResponse(String cmd, long waitTime) {
        String pattern1 = remoteName;// 行首

        String pattern2 = username+"@"+remoteName;
        StringBuffer buffer = new StringBuffer();
        String msg = getResponse(waitTime);
        msg = msg.replaceAll("\r", "");
        String[] retMsgs = msg.split("\n");
        for(String str : retMsgs){
            if (str.startsWith(pattern1)||str.startsWith(pattern2)){// 包含pattern的内容过滤掉

                continue;
            }else{
                buffer.append(str+"\n");
            }
        }
        return buffer.toString().trim();
    }

    /**

     * 读取分析结果

     *

     * @param pattern   匹配到该字符串时返回结果

     * @return

     */
    public String readUntil(String pattern,long waitTime) {
        StringBuffer sb = new StringBuffer();
        try {
            char ch;
            int code = -1;
            int available=instr.available();// 可读取多少字节内容

            if(available==0){
                Thread.sleep(waitTime);
                available=instr.available();
            }
            while (available!=0) {
                available=instr.available();// 可读取多少字节内容

                if(available==0){
                    Thread.sleep(waitTime);
                    available=instr.available();
                    continue;
                }
                code=instr.read();
                ch = (char)code;
                sb.append(ch);

            }


        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    public void readUntil(String str) {
        char last = str.charAt(str.length() - 1);
        String[] ss;
        try {
            StringBuffer sb = new StringBuffer();
            char c;
            int code = -1;
            boolean ansiControl = false;
            boolean start = true;
            while ((code = (instr.read())) != -1) {
                c = (char) code;
                if (c == '\033') {//vt100控制码都是以\033开头的。

                    ansiControl = true;
                    int code2 = instr.read();
                    char cc = (char) code2;
                    if (cc == '[' || cc == '(') {
                    }
                }
                if (!ansiControl) {
                    if (c == '\r') {
                        //这里是命令行中的每一句反馈

                        String olds = new String(sb.toString().getBytes(
                                ORIG_CODEC), TRANSLATE_CODEC);
                        System.out.println(olds);
                        if (sb.lastIndexOf(str) != -1) {
                            break;
                        }
                        sb.delete(0, sb.length());
                    } else if (c == '\n')
                        ;
                    else
                        sb.append(c);
                    if (sb.lastIndexOf(str) != -1) {
                        break;
                    }
                }

                if (ansiControl) {
                    if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
                            || c == '"') {
                        ansiControl = false;
                    }
                }
            }
            System.out.println(new String(sb.toString().getBytes(ORIG_CODEC),
                    TRANSLATE_CODEC));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void write(String s) {
        try {
            out.write(s.getBytes());
            out.flush();
            System.out.println(s);
        } catch (Exception e) {
        }
    }
}
